package com.shigu.mo.services;

import com.alibaba.fastjson.JSON;
import com.opentae.data.mall.beans.MoCard;
import com.opentae.data.mall.beans.MoOrder;
import com.opentae.data.mall.beans.MoPassagewayAccount;
import com.opentae.data.mall.examples.MoCardExample;
import com.opentae.data.mall.examples.MoOrderExample;
import com.opentae.data.mall.examples.MoPassagewayAccountExample;
import com.opentae.data.mall.interfaces.MoCardMapper;
import com.opentae.data.mall.interfaces.MoOrderMapper;
import com.opentae.data.mall.interfaces.MoPassagewayAccountMapper;
import com.shigu.linkage.sdks.exceptions.LinkageException;
import com.shigu.linkage.sdks.requests.ConsumeSMSRequest;
import com.shigu.linkage.sdks.requests.LinkageRequest;
import com.shigu.linkage.sdks.requests.TradeRequest;
import com.shigu.linkage.sdks.responses.*;
import com.shigu.main4.common.util.MoneyUtil;
import com.shigu.mo.bo.requests.LinkageMsgRequest;
import com.shigu.mo.bo.requests.LinkageSubmitRequest;
import com.shigu.mo.utils.Base64Util;
import com.shigu.mo.utils.RSAUtils;
import com.shigu.mo.vo.responses.LinkagePayInfoResponse;
import com.shigu.passageway.exceptions.PassagewayException;
import com.shigu.route.PassagewayRoute;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.PublicKey;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 供联动专用服务
 */
@Service
public class BusinessLinkageService {

    private static final Logger logger = LoggerFactory.getLogger(BusinessLinkageService.class);
    @Autowired
    MoOrderMapper moOrderMapper;

    @Autowired
    MoPassagewayAccountMapper moPassagewayAccountMapper;

    @Autowired
    MoCardMapper moCardMapper;

    @Autowired
    PassagewayRoute passagewayRoute;

    Long passagewayId=3L;

    @Value("${main_host}")
    private String MAIN_HOST;

    /**
     * 查交易信息
     * @param oid
     * @return
     */
    public LinkagePayInfoResponse selPayInfo(Long oid){
        MoOrder order=moOrderMapper.selectByPrimaryKey(oid);
        LinkagePayInfoResponse response=new LinkagePayInfoResponse();
        response.setAmount(order.getMoney());
        response.setCashCard(order.getCashNo());
        response.setTradecard(order.getCreditNo());
        MoCardExample cardExample=new MoCardExample();
        cardExample.createCriteria().andUserIdEqualTo(order.getUserId()).andBankNoEqualTo(order.getCreditNo());
        cardExample.setStartIndex(0);
        cardExample.setEndIndex(1);
        List<MoCard> cards=moCardMapper.selectByConditionList(cardExample);
        if (cards.size()>0) {
            MoCard card=cards.get(0);
            response.setCnv2(card.getCvv()==null?"":card.getCvv());
            response.setDate(card.getExpireDate()==null?"":card.getExpireDate());
            response.setTelephone(card.getTelephone()==null?"":card.getTelephone());
        }
        return response.success();
    }

    /**
     * 申请发送验证码
     * @param req
     */
    public void sendPayMsg(LinkageMsgRequest req) throws Exception {
        MoOrder order=moOrderMapper.selectByPrimaryKey(Long.valueOf(req.getOid()));
        MoPassagewayAccount account=moPassagewayAccountMapper.selByUserId(order.getUserId(),passagewayId);

        ConsumeSMSRequest request=new ConsumeSMSRequest();
        request.setOrderNo(order.getOrderCode());
        request.setAmount(order.getMoney());
        request.setMerchCode(LinkageRequest.merchantCode);
        request.setSubMerchCode(account.getAccountCode());
        request.setGoodsName("黄金珠宝");
        request.setChannelCode("fastSoopay");
        request.setTypeCode("T0");
        request.setCriditNo(order.getCreditNo());
        request.setBankPhoneNo(req.getTelephone());
        request.setNotifyUrl(MAIN_HOST+"bus/linkageTradecall.htm");//回调通知
//        request.setNotifyUrl("http://kjt01.hz.taeapp.com/callbacktest.htm");//回调通知
        request.setCvv(secretCvv(req.getCvv()));
        request.setExpireDate(formatExpireDate(req.getDate()));//要处理成mmyy
        ConsumeSMSResponse response=request.exec();
//        logger.warn(req.getOid()+":"+ JSON.toJSONString(req)+" res:"+response.resultBody());
        if (!response.getFlag()) {
            throw new LinkageException(response.getErrorMessage());
        }
    }

    /**
     * 支付确认
     * @param bo
     */
    public void paySure(LinkageSubmitRequest bo) throws Exception {
        MoOrder order=moOrderMapper.selectByPrimaryKey(Long.valueOf(bo.getOid()));
        MoPassagewayAccount account=moPassagewayAccountMapper.selByUserId(order.getUserId(),passagewayId);
        TradeRequest req=new TradeRequest();
        req.setOrderNo(order.getOrderCode());
        req.setSubMerchCode(account.getAccountCode());
        req.setAmount(order.getMoney());
        req.setNotifyUrl(MAIN_HOST+"bus/linkageTradecall.htm");
//        req.setNotifyUrl("http://kjt01.hz.taeapp.com/callbacktest.htm");
        req.setSmsCode(bo.getVerify());
        req.setCvv(secretCvv(bo.getCvv()));
        req.setExpireDate(formatExpireDate(bo.getDate()));
        req.setChannelCode("fastSoopay");
        req.setCriditNo(order.getCreditNo());
        req.setBankPhoneNo(bo.getTelephone());
        TradeResponse res=req.exec();
        if (!res.getFlag()) {
//            logger.warn(bo.getOid()+"trade:"+ JSON.toJSONString(req)+" res:"+res.resultBody());
            throw new LinkageException(res.getErrorMessage());
        }
        //保存cvv和telephone和date
        MoCardExample cardExample=new MoCardExample();
        cardExample.createCriteria().andUserIdEqualTo(order.getUserId()).andBankNoEqualTo(order.getCreditNo());
        MoCard card=new MoCard();
        card.setCvv(bo.getCvv());
        card.setExpireDate(bo.getDate());
        card.setTelephone(bo.getTelephone());
        moCardMapper.updateByExampleSelective(card,cardExample);
    }

    /**
     * 验证交易是否成功
     * @param oid
     * @return
     */
    public boolean checkOrder(Long oid){
        MoOrder order=moOrderMapper.selectByPrimaryKey(oid);
        return order.getStatus()==3;
    }

    /**
     * 进件回调
     * @param bo
     */
    public void registCallback(SubMerchantRegistResponse bo){
        RegistSynData data=bo.getReturn_value();
        if (data == null) {
            return;
        }
        String outerId=data.getOutMerchantCode();
        Integer status=2;
        String subId=data.getSubMerchantCode();
        if (!bo.isSuccess()) {
            status=3;
            logger.error(outerId+"进件审核不通过:"+JSON.toJSONString(bo.getReturn_value()));
        }
        MoPassagewayAccountExample example=new MoPassagewayAccountExample();
        example.createCriteria().andAccountCodeEqualTo(outerId).andPassagewayIdEqualTo(passagewayId);
        MoPassagewayAccount account=new MoPassagewayAccount();
        account.setExamineStatus(status);
        if (StringUtils.isNotEmpty(subId)) {
            account.setAccountCode(subId);
        }
        moPassagewayAccountMapper.updateByExampleSelective(account,example);
    }

    /**
     * 联动回调
     * @param bo
     */
    public void payCallback(TradeCallbackResponse bo) throws PassagewayException {
        Double amount=Double.valueOf(bo.getTradeTotal());
        amount= MoneyUtil.formatMoneyDouble(amount);
        MoOrderExample example=new MoOrderExample();
        example.createCriteria().andOrderCodeEqualTo(bo.getOrderno());
        List<MoOrder> orders=moOrderMapper.selectByExample(example);
        if (orders.size()==0) {
            logger.error(bo.resultBody());
            return;
        }
        if (!bo.getStatus().equals("Y")) {
            logger.error(bo.resultBody());
        }
        MoOrder order=orders.get(0);
        Double fee=Double.valueOf(order.getRate())*Double.valueOf(order.getMoney());
        passagewayRoute.selwayByPid(passagewayId).payCallBack(order.getOrderId(),amount,fee,bo.getStatus());
    }

    /**
     * 对cvv进行加密
     * @param cvv
     * @return
     * @throws Exception
     */
    private String secretCvv(String cvv) throws Exception {
        FileInputStream inPublic = new FileInputStream(
                BusinessLinkageService.class.getClassLoader().getResource("").getPath() + "/linkage_rsa_public_key.pem");
        PublicKey publicKey = RSAUtils.loadPublicKey(inPublic);
        // 加密
        byte[] encryptByte = RSAUtils.encryptData(cvv.getBytes(), publicKey);
        return Base64Util.encode(encryptByte);
    }

    /**
     * 格式化有效期
     * @param date
     * @return
     */
    private String formatExpireDate(String date){
        return date.substring(2,4)+date.substring(0,2);
    }
}
